
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Spring Boot 调用 ChatGPT接口 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Spring Boot 调用 ChatGPT接口 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在开始使用 Spring Boot 调用 ChatGPT API 之前，需要准备哪些关键事项？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">首先需要注册 OpenAI 账号并生成一个 API 密钥。其次，开发环境需要满足以下要求：JDK 8 或更高版本、Maven 或 Gradle 构建工具，以及一个 IDE（如 IntelliJ IDEA）。</div>
          </div>
          <div class="card-source">来源: 1. 准备工作</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">配置</div>
          <div class="card-question">为了让 Spring Boot 应用能够连接到 OpenAI 服务，需要在 `application.properties` 文件中配置哪两个核心属性？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">配置</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">需要在 `application.properties` 文件中配置 `openai.api.key` 用于存放你的 OpenAI API 密钥，以及 `openai.api.url` 用于指定 API 的请求地址，例如 `https://api.openai.com/v1/chat/completions`。</div>
          </div>
          <div class="card-source">来源: 3.2 配置文件</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在 `ChatGPTService` 类中，`RestTemplate` 实例扮演了什么角色？它是如何实现与 OpenAI API 的交互的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`RestTemplate` 用于发送 HTTP 请求。它通过 `postForEntity` 方法，将包含了模型、消息内容和认证头（API Key）的 `HttpEntity` 对象以 POST 方式发送到 OpenAI API 的 URL，并接收返回的响应。</div>
          </div>
          <div class="card-source">来源: 4.3 实现服务类</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">根据文档，用于发送给 ChatGPT API 的请求模型 `ChatGPTRequest` 包含哪些主要字段？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`ChatGPTRequest` 模型主要包含两个字段：一个名为 `model` 的字符串（例如 "gpt-3.5-turbo"），以及一个名为 `messages` 的 `Message` 对象列表。每个 `Message` 对象则包含 `role` 和 `content` 两个字段。</div>
          </div>
          <div class="card-source">来源: 4.2 创建请求和响应模型</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">诊断</div>
          <div class="card-question">当调用 OpenAI API 时，如果遇到 `429 Too Many Requests` 错误并且错误类型为 `insufficient_quota`，这通常意味着什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">诊断</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">这个错误意味着与 API 密钥关联的账户的免费测试额度已经用完。要继续使用，用户需要为 API 调用付费或更换一个新的账户以获取新的免费额度。</div>
          </div>
          <div class="card-source">来源: 调用过程可能出现的问题</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">优化</div>
          <div class="card-question">文档中提到了哪些可以用于优化和扩展该 Spring Boot 服务的建议？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">优化</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档提出了四点建议：1. 使用 `@Async` 或 `CompletableFuture` 实现异步调用以提高性能；2. 添加缓存机制（如 Redis）减少重复请求的 API 调用次数；3. 构建前端界面提供交互功能；4. 支持动态切换 AI 模型（如 gpt-4）。</div>
          </div>
          <div class="card-source">来源: 6. 优化与扩展</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在 `ChatGPTController` 中，是如何定义一个接收用户提问的 API 端点的？请描述其路径、请求方法和参数。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过 `@RestController` 和 `@RequestMapping("/api/chatgpt")` 注解定义控制器。使用 `@PostMapping("/ask")` 注解创建了一个处理 POST 请求的端点，其完整路径是 `/api/chatgpt/ask`。它通过 `@RequestBody` 注解接收一个字符串类型的 `userInput` 作为请求体。</div>
          </div>
          <div class="card-source">来源: 4.4 创建控制器</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在向 OpenAI API 发送请求时，是如何进行身份验证的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">身份验证是通过在 HTTP 请求头中设置 `Authorization` 字段来完成的。具体实现是使用 Bearer Token 认证方式，将 OpenAI API 密钥作为 Bearer Token 的值，代码中通过 `headers.setBearerAuth(openAIConfig.getApiKey())` 实现。</div>
          </div>
          <div class="card-source">来源: 4.3 实现服务类</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">在创建 Spring Boot 项目时，除了 `Spring Web` 之外，文档还建议添加了哪些初始依赖项？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档建议在 Spring Initializer 中添加三个依赖项：`Spring Web` 用于构建 Web 应用，`Spring Boot DevTools` 用于热部署和开发辅助，以及 `Spring Configuration Processor` 用于在IDE中更好地处理自定义配置属性。</div>
          </div>
          <div class="card-source">来源: 2.1 使用 Spring Initializer 创建项目</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
